I'm building this site and right now i have 4 divs that do basically the same thing, but theyre being copy and pasted 4 times and just like 4 bits of information are being changed from them. is there any way using react that i can make it so its only one div and a function handles the different parameters needed for the divs? here is is a quick example.
quickExample.jsx
import React, {useRef} from "react";
function test(props) {
animalAmount = useRef(20);
return (
<div>
<div id='turtle-id'>
<h1>I like turtles!</h1>
<p>there are {animalAmount.current} turtles in my house!</p>
<button>Click me!</button>
</div>
<div id='dog-id'>
<h1>I like dogs!</h1>
<p>there are {animalAmount.current} dogs in my house!</p>
<button>Click me!</button>
</div>
<div id='fish-id'>
<h1>I like fish!</h1>
<p>there are {animalAmount.current} fish in my house!</p>
<button>Click me!</button>
</div>
<div id='hippo-id'>
<h1>I like hippos!</h1>
<p>there are {animalAmount.current} hippos in my house!</p>
<button>Click me!</button>
</div>
</div>
);
}
export default test;
for specific reasons I cant just create a parent component and call it there and duplicate it four times, it needs to be done in this component if possible.
Create an array with your data, and then use map to print the divs:
const data = [
{
id: 'turtle-id',
title: 'I like turtles',
text: '...',
// rest of needed data
}, {
// ...
}
];
return (
data.map(item => {
return (
<div key={item.id} id={item.id}>
<h1>{item.title}</h1>
<p>{item.text}</p>
<button>Click me!</button>
</div>
);
});
);
You can create an array of objects outside of component and loop through them. Something like this.
const animals = [{
id: "turtle-id",
title: "I like turtles!",
defineText: (value) => `there are ${value} turtles in my house!`
}, ....]
and then in your component's return, you can do something like this.
...
return (
<div>
{animals.map((animal) => {
return (
<div key={animal.id} id={animal.id}>
<h1>{animal.title}</h1>
<p>{animal.defineText(animalAmount.current)}</p>
<button>Click me!</button>
</div>
);
})}
</div>
);
...
Have a set of data describing the animals and set your state with it.
Shift your animal containers into a new component (Animal).
map over the animals state to create a series of Animals.
When a button is clicked update the count value of that animal.
const { useState } = React;
// Pass in some data
function Animals({ data }) {
// Initialise state with the data
const [ animals, setAnimals ] = useState(data);
// Copy the state, find the name of the
// animal we're updating the count for from
// the container's dataset, find the index of the
// animal object in state, update its count value
// and the update the state
function handleCount(e) {
const copy = [...animals];
const { name } = e.target.closest('.animal').dataset;
const index = copy.findIndex(obj => obj.name === name);
++copy[index].count;
setAnimals(copy);
}
// `map` over the animals state
// an return an array of Animal components
return animals.map(animal => {
return (
<Animal
animal={animal}
handleCount={handleCount}
/>
);
});
}
// Animal component
function Animal({ animal, handleCount }) {
return (
<div className="animal" data-name={animal.name}>
<h1>I like {animal.plural}!</h1>
<p>There are {animal.count} {animal.plural} in my house!</p>
<button onClick={handleCount}>Click me!</button>
</div>
);
}
const data = [
{ name: 'turtle', plural: 'turtles', count: 0 },
{ name: 'dog', plural: 'dogs', count: 0 },
{ name: 'fish', plural: 'fish', count: 0 },
{ name: 'hippo', plural: 'hippos', count: 0 }
];
ReactDOM.render(
<Animals data={data} />,
document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>